package com.liuguangzhou.service.impl;

import com.liuguangzhou.model.User;
import com.liuguangzhou.utils.KeyNameUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @Classname UserServiceImpl
 * @Author liuguangzhou
 * @Date 2020-04-07
 */
@Service
@Slf4j
public class UserServiceImpl {
    @Autowired
    private RedisTemplate redisTemplate;

    @Resource(name = "redisTemplate")
    private ValueOperations<String, String> string;

    @Resource(name ="redisTemplate")
    private HashOperations<String, String, User> hset;


    /**
     * Redis有什么前令，Jedis 有什么力法
     * --》Lettuce -->RedisTemplate (Jedis/... )进一一步的封装。
     * RedisTemplate方法和命令肯定不一样。
     * Redis String 类型
     * 需求:用户输入一个key,
     * 先判断Redis中是否存在该数据，
     * 如果存在，在Redis中进行查询， 并返回
     * 如果不存在，在MYSQL 数据库查询。将结果赋给Redis，并返回
     *
     * @param key
     * @return
     */
    public String getString(String key) {
        log.info("测试----------------");
        if (redisTemplate.hasKey(key)) {
//            return (String) redisTemplate.opsForValue().get(key);
            return string.get(key);
        } else {
            String value = "RedisTemplate模板测试";
            redisTemplate.opsForValue().set(key, value);
            return value;
        }
    }


    /**
     * 设置key的有效期  有了RedisTemplate模板就不需要自己写Utils了
     *
     * @param key
     * @param valve
     */
    public void expireStr(String key, String valve) {
        redisTemplate.opsForValue().set(key, valve);
        redisTemplate.expire(key, 2, TimeUnit.HOURS);
    }


    public User getUserById(String id) {
        if (redisTemplate.opsForHash().hasKey("user", id)) {
            log.info("-----------从Redis中查询");

            return (User) redisTemplate.opsForHash().get("user", id);

        } else {
            log.info("---------从数据库中查询");
            User user = new User();
            user.setId(id);
            user.setUserName("刘广周");
            user.setAge(18);

            //存入Redis
            redisTemplate.opsForHash().put("user",id,user);
            return user;

        }
    }


    public User getUserById2(String id) {
        if (redisTemplate.opsForHash().hasKey(KeyNameUtil.USER, id)) {
            log.info("-----------从Redis中查询");

            return (User) redisTemplate.opsForHash().get(KeyNameUtil.USER, id);

        } else {
            log.info("---------从数据库中查询");
            User user = new User();
            user.setId(id);
            user.setUserName("刘广周");
            user.setAge(18);

            //存入Redis
//            redisTemplate.opsForHash().put(User.getKeyName(),id,user);
            hset.put(User.getKeyName(),id,user);
            return user;

        }
    }


    /**
     * 在getUserById中出现了很多 user 这种钥匙改了名字怎么办 需要一个一个该
     * 1、可以封装一个Util类 用来进行统一  例如 KeyNameUtil.USER
     * 2、可以是在user实体类中 加一个方法来获取 user 例如  User.getKeyName()
     *
     *
     * 使用RedisTempla模板
     * 写string  redisTemplate.opsForValue().set(key, valve)
     * 写hset  redisTemplate.opsForHash().get(KeyNameUtil.USER, id)
     * 太长了 可以用 @resource来简化
     *
     *
     */


    /**
     * 查询用户有没有没锁定
     * @param key
     * @return
     */
    public Long userLoginLock(String key){
        if (redisTemplate.hasKey(key)){
            return redisTemplate.getExpire(key,TimeUnit.MINUTES);
        }else {
            return -1L;
        }
    }

    /**
     * 模拟登录 先返回null 表示登录失败
     */
    public User login(String userName,String password){
        return null;
    }


    /**
     * 查询用户登录
     * @param
     * @return
     */
    public String userLoginValue(String userName){
        String key=User.getLoginValueKey(userName);
        int maxNumber=5;
        //如果不存在 第一次登录失败 设置失效期2分钟
        if (!redisTemplate.hasKey(key)){
            redisTemplate.opsForValue().set(key,1);
            //使用RedisTemplate赋值有效期时 不能赋值时设置 会失效
            redisTemplate.expire(key,2,TimeUnit.MINUTES);
            return "登录失败 2分钟内还可以输入"+(maxNumber-1)+"次";
        }else {
            //看看一下 登录了几次
            Long count  = Long.parseLong(redisTemplate.opsForValue().get(key).toString());
            if(count<(maxNumber-1)){
                //次数加一
                redisTemplate.opsForValue().increment(key,1);
                return userName+"用户登录失败"+redisTemplate.getExpire(key,TimeUnit.SECONDS)+
                        "秒内还可以输入"+(maxNumber-count-1)+"次";
            }else {
                redisTemplate.opsForValue().set(User.getLoginTimeLockKey(userName),"1");
                redisTemplate.expire(User.getLoginTimeLockKey(userName),2,TimeUnit.HOURS);
                return "登录失败 2小时后来";

            }
        }
    }

}
